package com.cnswhy.cloud.server.app.controller.spell;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cnswhy.cloud.common.core.mybatis.conditions.Wraps;
import com.cnswhy.cloud.common.core.utils.BaseUtils;
import com.cnswhy.cloud.common.core.utils.CnswhyUtil;
import com.cnswhy.cloud.common.logging.uitls.MDCUtil;
import com.cnswhy.cloud.common.rabbitmq.service.MessageService;
import com.cnswhy.cloud.common.redis.service.IdGeneratorService;
import com.cnswhy.cloud.common.redis.service.RedisService;
import com.cnswhy.cloud.server.app.config.JsApiPay;
import com.cnswhy.cloud.server.app.config.WxPayApi;
import com.cnswhy.cloud.server.app.config.WxPayData;
import com.cnswhy.cloud.server.common.entity.constant.AmqpExchange;
import com.cnswhy.cloud.server.common.entity.enumeration.*;
import com.cnswhy.cloud.server.common.entity.mq.OrderQueryMQ;
import com.cnswhy.cloud.server.core.service.shop.ShopProductStockService;
import com.cnswhy.cloud.server.core.utils.PasswordCoder;
import com.cnswhy.cloud.server.app.utils.RSAUtils;
import com.cnswhy.cloud.server.core.channel.service.SandeService;
import com.cnswhy.cloud.server.core.config.*;
import com.cnswhy.cloud.server.core.constant.RedisConstant;
import com.cnswhy.cloud.server.app.controller.BaseController;
import com.cnswhy.cloud.server.core.entity.*;
import com.cnswhy.cloud.server.core.query.QueryGenerator;
import com.cnswhy.cloud.server.core.entity.ShopProduct;
import com.cnswhy.cloud.server.core.service.SysConfigService;
import com.cnswhy.cloud.server.core.service.customer.CustomerService;
import com.cnswhy.cloud.server.core.service.spell.BuyBackOrderService;
import com.cnswhy.cloud.server.core.service.shop.ShopProductService;
import com.cnswhy.cloud.server.core.service.spell.SpellOrderService;
import com.cnswhy.cloud.server.core.service.spell.SpellPriceService;
import com.cnswhy.cloud.server.core.vo.RespVo;
import com.cnswhy.cloud.server.core.wallet.WalletService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;

@Controller
@RequestMapping("/backOrder")
@Slf4j
public class BuyBackOrderController extends BaseController {
    @Autowired
    IdGeneratorService idGeneratorService;
    @Autowired
    private BuyBackOrderService buyBackOrderService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private SpellOrderService spellOrderService;

    @Autowired
    private ShopProductService shopProductService;
    @Autowired
    SpellPriceService spellPriceService;

    @Autowired
    SandeService sandeService;
    @Autowired
    SysConfigService sysConfigService;
    @Autowired
    WalletService walletService;
    @Autowired
    private CustomerService customerService;
    @Autowired
    private MessageService messageService;
    @Autowired
    private ShopProductStockService shopProductStockService;

    @RequestMapping("/queryBackRate")
    @ResponseBody
    public RespVo queryBackRate() {
        log.info("查询回购费率");
        RespVo vo = new RespVo();
        String backRate = (String) redisService.hget(RedisConstant.SYS_CONFIG_2, RedisConstant.BUY_BACK_PRICE);
        vo.setCode(RespVo.CODE_SUCCESS);
        vo.setResult(backRate);
        return vo;
    }


    @RequestMapping("/ajaxOrderPage")
    @ResponseBody
    public RespVo ajaxOrderPage(BuyBackOrder bo,
                                @RequestParam(name = "currentPage", defaultValue = "1") Integer currentPage,
                                @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest request) {
        log.info("查询回购订单:{}", JSON.toJSONString(bo), currentPage, pageSize);
        RespVo vo = new RespVo();
        try {
            Customer loginCustomer = getLoginCustomer( request);
            bo.setCustomerId(loginCustomer.getId());
            QueryWrapper<BuyBackOrder> queryWrapper = QueryGenerator.initQueryWrapper(bo);
            queryWrapper.orderByDesc("create_time");
            Page<BuyBackOrder> page = new Page<>(currentPage, pageSize);
            IPage<BuyBackOrder> pageList = buyBackOrderService.page(page, queryWrapper);

            String prefix = (String) redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.FTP_PATH_PREFIX);
            JSONObject object = new JSONObject();
            object.put("pageList", pageList);
            object.put("photosUrl", prefix);

            vo.setCode(RespVo.CODE_SUCCESS);
            vo.setResult(object);
        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("查询回购区订单失败");
            log.error("查询回购区订单失败", e);
        }
        return vo;
    }

    @RequestMapping("/ajaxPageData")
    @ResponseBody
    public RespVo ajaxPageData(SpellOrder bo,
                               @RequestParam(name = "currentPage", defaultValue = "1") Integer currentPage,
                               @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        log.info("查询回购区商品:{}", JSON.toJSONString(bo), currentPage, pageSize);
        RespVo vo = new RespVo();
        try {
            QueryWrapper<SpellOrder> queryWrapper = QueryGenerator.initQueryWrapper(bo);
            queryWrapper.orderByDesc("create_time");
            Page<SpellOrder> page = new Page<>(currentPage, pageSize);
            IPage<SpellOrder> pageList = spellOrderService.page(page, queryWrapper);
            JSONObject jsonPage = JSON.parseObject(JSON.toJSONString(pageList));
            JSONArray jsonArray = new JSONArray();
            String pfx = String.valueOf(redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.FTP_PATH_PREFIX));
            for (var var : pageList.getRecords()) {
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(var));
                SpellPrice spellPrice = spellPriceService.getById(var.getPriceId());
                if (spellPrice == null) {
                    continue;
                }
                ShopProduct shopProduct = shopProductService.getById(var.getProductId());
                if (shopProduct == null) {
                    continue;
                }
                jsonObject.put("priceTitle", spellPrice.getTitle());
                jsonObject.put("productName", shopProduct.getProductName());
                if(StringUtils.isNotBlank(shopProduct.getUrl())){
                    jsonObject.put("productImg", shopProduct.getUrl());
                }else{
                    jsonObject.put("productImg", pfx+ shopProduct.getThumbnailImg());
                }

                jsonArray.add(jsonObject);
            }
            jsonPage.put("records", jsonArray);
            vo.setCode(RespVo.CODE_SUCCESS);
            vo.setResult(jsonPage);
        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("查询回购区商品失败");
            log.error("查询回购区商品失败", e);
        }
        return vo;
    }

    @RequestMapping("/saveBackOrder")
    @ResponseBody
    public RespVo saveBackOrder(Long id, Integer payType, Long addressId, HttpServletRequest request) {
        log.info("回购区下单:{} {} {}", id, payType, addressId);
        RespVo vo = new RespVo();
        try {
            BuyBackOrder order = new BuyBackOrder();
            SpellOrder spellOrder = spellOrderService.getById(id);
            if (spellOrder == null) {
                vo.setCode(RespVo.CODE_ERROR);
                vo.setMessage("查询不到订单信息");
                return vo;
            }
            order.setSpellOrderId(id);
            order.setProductId(spellOrder.getProductId());
            Customer loginCustomer = getLoginCustomer( request);
            order.setCustomerId(loginCustomer.getId());
            order.setLoginName(loginCustomer.getLoginName());
            ShopProduct product = shopProductService.getById(spellOrder.getProductId());
            order.setProductName(product.getProductName());
            order.setProductImg(product.getThumbnailImg());
            order.setPayType(payType);
            order.setStockId(spellOrder.getStockId());
            if(order.getStockId() != null){
                ShopProductStock shopProductStock = shopProductStockService.getById(order.getStockId());
                order.setSpecValues(shopProductStock.getSpecValues());
            }
            order.setOrderNum("B" + idGeneratorService.genCommonIdString());
            order.setStatus(1);
            order.setBackType(1);
            String backRate = (String) redisService.hget(RedisConstant.SYS_CONFIG_2, RedisConstant.BUY_BACK_PRICE);
            order.setOriginalPrice(spellOrder.getOrderPrice());
            order.setOrderPrice(spellOrder.getOrderPrice().multiply(new BigDecimal(backRate)));
            order.setAddressId(addressId);
            order.setExpressCompany(ExpressCompany.UNKNOWN);
            buyBackOrderService.save(order);
            vo.setCode(RespVo.CODE_SUCCESS);
            vo.setResult(order.getOrderNum());
        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("下单失败");
            log.error("回购区下单失败", e);
        }
        return vo;
    }

    @RequestMapping("/alipayPay")
    @ResponseBody
    public RespVo alipayPay(HttpServletRequest request, HttpServletResponse response, String orderNum) {
        log.info("支付宝支付:{}", orderNum);

        RespVo respVo = new RespVo();
        try {
            if (StringUtils.isBlank(orderNum)) {
                respVo.setCode(RespVo.CODE_VERIFY);
                respVo.setMessage("参数异常");
                return respVo;
            }
            String price = "";
            String body = "BACK-SHOPPING";

            //取库中支付宝参数
            SysConfig sysConfig = sysConfigService.getOne(Wraps.<SysConfig>lbQ().eq(SysConfig::getConfigKey, "aliPaySys").eq(SysConfig::getDisplayStatus, "1"));

            BuyBackOrder queryByOrderNum = buyBackOrderService.getOne(Wraps.<BuyBackOrder>lbQ().eq(BuyBackOrder::getOrderNum, orderNum));

            orderNum = "B" + idGeneratorService.genCommonIdString();
            queryByOrderNum.setOrderNum(orderNum);
            buyBackOrderService.updateById(queryByOrderNum);

            price = queryByOrderNum.getOrderPrice().toString();
            AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, sysConfig.getConfigValue(),
                    sysConfig.getValidateRules(), AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                    sysConfig.getConfigRules(), AlipayConfig.SIGNTYPE);
            // AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();

            AlipayTradeAppPayRequest alipay_request = new AlipayTradeAppPayRequest();
            // 封装请求支付信息
            AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
            model.setOutTradeNo(orderNum);
            model.setSubject("支付订单" + orderNum);
            model.setTotalAmount(price);
            model.setBody(body);
            model.setTimeoutExpress("2m");
            model.setProductCode("QUICK_MSECURITY_PAY");
            alipay_request.setBizModel(model);


            // 设置异步通知地址
            alipay_request.setNotifyUrl(
                    (String) redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.ALIPAY_NOTIFY_URL));
            // 设置同步地址
            alipay_request.setReturnUrl("http://renrenpin.shop/#/pages/my/order/order?idx=0");
            AlipayTradeAppPayResponse alipayTradeAppPayResponse = client.sdkExecute(alipay_request);
            // 就是orderString 可以直接给APP请求，无需再做处理。
            String orderString = alipayTradeAppPayResponse.getBody();
            log.error(orderString);
            respVo.setResult(orderString);
            respVo.setCode(0);
            OrderQueryMQ orderQueryMQ = OrderQueryMQ.builder().orderId(orderNum).queryTimes(0L).build();
            orderQueryMQ.setPayType(PayType.alipay);
            orderQueryMQ.setBody(body);
            orderQueryMQ.setTraceId(MDCUtil.getTraceId());
            messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("调用支付宝发起支付请求异常");
            log.error("支付宝拉起失败", e);
        }
        return respVo;
    }


    @RequestMapping("/wxPay")
    @ResponseBody
    public RespVo wxPay(String orderNum, String client, HttpServletRequest request) {
        log.info("微信支付:{}", orderNum);

        RespVo respVo = new RespVo();
        try {
            //取库中微信参数
            SysConfig sysConfig = sysConfigService.getOne(Wraps.<SysConfig>lbQ().eq(SysConfig::getConfigKey, "wxPaySys").eq(SysConfig::getDisplayStatus, "1"));

            BigDecimal price = BigDecimal.ZERO;
            String body = "BACK-SHOPPING";
            //BuyBackOrder queryByOrderNum = buyBackOrderService.queryByOrderNum(orderNum);
            BuyBackOrder queryByOrderNum = buyBackOrderService.getOne(Wraps.<BuyBackOrder>lbQ().eq(BuyBackOrder::getOrderNum, orderNum));
            price = queryByOrderNum.getOrderPrice();

            BigDecimal multiply = price.multiply(new BigDecimal("100"));
            String notifyUrl = (String) redisService.hget(RedisConstant.SYS_CONFIG_1, RedisConstant.WX_NOTIFY_URL);
            JsApiPay jsApiPay = new JsApiPay(null, multiply.intValue(), sysConfig.getValidateRules(), sysConfig.getConfigValue(),
                    notifyUrl, sysConfig.getConfigRules(), "", "APP");
            WxPayData wxData = jsApiPay.GetUnifiedOrderResult("GOODS_TRADE", "交易编号：" + orderNum, orderNum, body,CnswhyUtil.getHttpServletRequestIpAddress());
            if (StringUtils.equals(wxData.GetValue("return_code").toString(), "SUCCESS")
                    && StringUtils.equals(wxData.GetValue("result_code").toString(), "SUCCESS")) {
                Date beijingDate = Calendar.getInstance(Locale.CHINA).getTime();
                String timeStamp = String.valueOf(beijingDate.getTime() / 1000);
                SortedMap<String, Object> map2 = new TreeMap<String, Object>();
                map2.put("appid", sysConfig.getConfigValue());
                map2.put("timestamp", timeStamp);
                map2.put("noncestr", wxData.GetValue("nonce_str"));
                map2.put("prepayid", wxData.GetValue("prepay_id"));
                map2.put("package", "Sign=WXPay");
                map2.put("partnerid", wxData.GetValue("mch_id"));
                String paySign = WxPayApi.createSign(map2, sysConfig.getConfigRules());
                map2.put("sign", paySign);
                respVo.setCode(RespVo.CODE_SUCCESS);
                respVo.setResult(map2);
                OrderQueryMQ orderQueryMQ = OrderQueryMQ.builder().orderId(orderNum).queryTimes(0L).build();
                orderQueryMQ.setPayType(PayType.wx);
                orderQueryMQ.setBody(body);
                orderQueryMQ.setTraceId(MDCUtil.getTraceId());
                messageService.sendAndQueryTimes(AmqpExchange.ORDER_QUERY_MESSAGE, orderQueryMQ, orderQueryMQ.getQueryTimes());
            } else {
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("发起微信支付失败");
            }
        } catch (Exception e) {
            log.error("调用微信支付请求异常：", e);
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("发起微信支付失败");
        }

        return respVo;
    }

    @RequestMapping("/updateStatus")
    @ResponseBody
    public RespVo updateStatus(BuyBackOrder order) {
        log.info("确认收货成功:{}", JSON.toJSONString(order));
        RespVo vo = new RespVo();
        try {
            buyBackOrderService.updateById(order);
            vo.setCode(RespVo.CODE_SUCCESS);
            vo.setMessage("确认收货成功");
        } catch (Exception e) {
            vo.setCode(RespVo.CODE_ERROR);
            vo.setMessage("确认收货失败");
            log.error("确认收货失败", e);
        }
        return vo;
    }

    @RequestMapping("/sandePay")
    @ResponseBody
    public RespVo sandePay(String orderNum, HttpServletRequest request) {
        log.info("杉德支付:{}", orderNum);

        RespVo respVo = new RespVo();
        try {
            BuyBackOrder queryByOrderNum = buyBackOrderService.getOne(Wraps.<BuyBackOrder>lbQ().eq(BuyBackOrder::getOrderNum, orderNum));

            String returnOrderNum = "BU" + idGeneratorService.genCommonIdString();
            queryByOrderNum.setReturnOrderNum(returnOrderNum);
            buyBackOrderService.updateById(queryByOrderNum);
            BigDecimal price = queryByOrderNum.getOrderPrice();
            String ip = BaseUtils.getIpAddress(request);

            SysConfig sysConfig = sysConfigService.getOne(Wraps.<SysConfig>lbQ().eq(SysConfig::getConfigKey, "sd_notify_url"));

            String result = sandeService.payH5(returnOrderNum, price, ip, sysConfig.getConfigValue(), "http://renrenpin.shop/#/pages/my/order/order?idx=0");
            respVo.setCode(respVo.CODE_SUCCESS);
            respVo.setResult(result);
            respVo.setMessage("请求成功");
        } catch (Exception e) {
            log.error("调用杉德支付请求异常：", e);
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("发起杉德支付失败");
        }

        return respVo;
    }

    @ApiOperation(value = "回购订单余额支付")
    @RequestMapping("/DEFAULTPay")
    @ResponseBody
    public RespVo DEFAULTPay(HttpServletRequest request, HttpServletResponse response, String orderNum, String tradePass) {
        log.info("回购订单余额支付:{}", orderNum);

        RespVo respVo = new RespVo();
        try {
            if (StringUtils.isBlank(orderNum)) {
                respVo.setCode(RespVo.CODE_VERIFY);
                respVo.setMessage("参数异常");
                return respVo;
            }
            BuyBackOrder order = buyBackOrderService.getOne(Wraps.<BuyBackOrder>lbQ().eq(BuyBackOrder::getOrderNum, orderNum));
            if (StringUtils.isEmpty(tradePass)) {
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("请输入交易密码");
                return respVo;
            }
            Customer loginCustomer = getLoginCustomer( request);
            Customer customer = customerService.queryById(loginCustomer.getId());
            String password = null;
            password = RSAUtils.decryptString(tradePass);// 解密
            if (!StringUtils.equals(PasswordCoder.generatePassword(password), customer.getTradePass())) {
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("交易密码错误");
                return respVo;
            }
            CustomerWallet customerWallet = walletService.checkAndCreate(customer.getId(), WalletType.BALANCE,0L);
            if (!walletService.checkDed(customerWallet.getCustomerId(), WalletType.BALANCE, CnswhyUtil.getFen(order.getOrderPrice()))) {
                respVo.setCode(RespVo.CODE_ERROR);
                respVo.setMessage("余额不足");
                return respVo;
            }
            //walletService.ded(customer.getId(), WalletType.BALANCE, TransType.RECYCLE, CnswhyUtil.getFen(order.getOrderPrice()), order.getOrderNum());

            order.setStatus(2);
            order.setBackType(1);
            buyBackOrderService.saveOrUpdate(order);
            //更新拼团信息为已回购
            Long spellOrderId = order.getSpellOrderId();
            SpellOrder spellOrder = spellOrderService.getById(spellOrderId);
            spellOrder.setSendStatus(5);
            spellOrderService.updateById(spellOrder);
            Customer customer1 = customerService.queryById(spellOrder.getCustomerId());
            CustomerWallet customerWallet1 = walletService.checkAndCreate(customer1.getId(), WalletType.BALANCE, 0L);
            //walletService.add(customerWallet1.getCustomerId(), WalletType.BALANCE, TransType.BUY_BACK_CHARGE, CnswhyUtil.getFen(order.getOrderPrice()), TransType.COUPON_CHARGE.getCode() + order.getOrderNum());
            respVo.setCode(RespVo.CODE_SUCCESS);
            respVo.setMessage("支付成功");
        } catch (Exception e) {
            respVo.setCode(RespVo.CODE_ERROR);
            respVo.setMessage("调用余额支付请求异常");
            log.error("调用余额支付请求异常", e);
        }
        return respVo;
    }
}
